package com.saas.datasource.core;

import com.alibaba.druid.pool.DruidDataSource;
import com.saas.datasource.core.druid.DruidDataSourceConfig;
import com.saas.datasource.core.hikari.HikariCpConfig;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.sql.DataSource;
import java.util.Map;

@Component
public class DynamicDataInit {
    private final Logger logger = LoggerFactory.getLogger(DynamicDataInit.class);
    @Autowired
    private ApplicationContext ctx;
    @Autowired
    private DataSourceConfig dataSourceConfig;

    /**
     * 初始化
     */
    @PostConstruct
    public void init() {
        // 获取BeanFactory
        DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) ctx.getAutowireCapableBeanFactory();
        // 创建bean信息.
       // 循环saasDataBase从数据库查出的数据源列表，此处省略
        if("druid".equals(dataSourceConfig.getConfigType())) {
            BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(DruidDataSource.class);
            Map<String, DruidDataSourceConfig> dataSourceConfigMap = dataSourceConfig.getDlist();
            logger.info(dataSourceConfigMap.size() + "##d##size######");
            if (dataSourceConfigMap != null && dataSourceConfigMap.size() > 0) {
                DynamicDataSource dynamicDataSource = ctx.getBean("dynamicDataSourceMaster", DynamicDataSource.class);
                for (String key : dataSourceConfigMap.keySet()) {
                    DruidDataSourceConfig druidDataSourceConfig = dataSourceConfigMap.get(key);
                    logger.info(key + "##########" + druidDataSourceConfig.getDriverClassName());
                    beanDefinitionBuilder.addPropertyValue("url", druidDataSourceConfig.getUrl());
                    beanDefinitionBuilder.addPropertyValue("username", druidDataSourceConfig.getUsername());
                    beanDefinitionBuilder.addPropertyValue("password", druidDataSourceConfig.getPassword());
		            beanDefinitionBuilder.addPropertyValue("driverClassName", druidDataSourceConfig.getDriverClassName());
                    beanDefinitionBuilder.addPropertyValue("initialSize", druidDataSourceConfig.getInitialSize());
                    beanDefinitionBuilder.addPropertyValue("maxActive", druidDataSourceConfig.getMaxActive());
                    beanDefinitionBuilder.addPropertyValue("minIdle", druidDataSourceConfig.getMinIdle());
                    beanDefinitionBuilder.addPropertyValue("maxWait", druidDataSourceConfig.getMaxWait());
                    //动态注册bean. bean的名字为第一个参数、
                    defaultListableBeanFactory.registerBeanDefinition(key, beanDefinitionBuilder.getBeanDefinition());
                    //获取动态注册的bean.
                    DataSource testDataSource = ctx.getBean(key, DruidDataSource.class);
                    dynamicDataSource.myMap.put(key, testDataSource);//指定key为的数据源
                }
                dynamicDataSource.setTargetDataSources(dynamicDataSource.myMap);
                dynamicDataSource.afterPropertiesSet();//一定要执行这个方法 具体含义可以看父类代码
            }
        }else if("hikari".equals(dataSourceConfig.getConfigType())){
            Map<String, HikariCpConfig> hlist = dataSourceConfig.getHlist();
//            BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(HikariDataSource.class);
            logger.info(hlist.size() + "##h##size######");
            if (hlist != null && hlist.size() > 0) {
                DynamicDataSource dynamicDataSource = ctx.getBean("dynamicDataSourceMaster", DynamicDataSource.class);
                for (String key : hlist.keySet()) {
                    HikariCpConfig hikariCpConfig=hlist.get(key);
                    int minConns = hikariCpConfig.getMinConn();
                    if (minConns < 1) {
                        minConns = 1;
                        hikariCpConfig.setMinConn(minConns);
                    }
                    int maxConns = hikariCpConfig.getMaxConn();
                    if (maxConns < 1) {
                        maxConns = 1;
                        hikariCpConfig.setMaxConn(maxConns);
                    }
                    int connIdleTimeout = hikariCpConfig.getConnIdleTimeout() * 1000;
                    if (connIdleTimeout < 60000) {
                        // 最小一分钟
                        connIdleTimeout = 60000;
                        hikariCpConfig.setConnIdleTimeout(60);
                    }
                    int connBusyTimeout = hikariCpConfig.getConnBusyTimeout() * 1000;
                    if (connBusyTimeout < 30000) {
                        // 最小30秒钟
                        connBusyTimeout = 30000;
                        hikariCpConfig.setConnBusyTimeout(30);
                    }
                    int connMaxAge = hikariCpConfig.getConnMaxAge() * 1000;
                    if (connMaxAge < 600000) {
                        // 最小60分钟
                        connMaxAge = 600000;
                        hikariCpConfig.setConnMaxAge(60);
                    }
                    logger.info(key + "##########" + hikariCpConfig.getDriverClassName());
                    // HikariConfig
                    HikariConfig hikariConfig = new HikariConfig();
                    hikariConfig.setPoolName(key);
                    // 数据库驱动
                    hikariConfig.setDriverClassName(hikariCpConfig.getDriverClassName());
                    // 服务器连接字符串
                    hikariConfig.setJdbcUrl(hikariCpConfig.getUrl());
                    // 登陆用户名
                    hikariConfig.setUsername(hikariCpConfig.getUsername());
                    // 登陆密码
                    hikariConfig.setPassword(hikariCpConfig.getPassword());
                    // 测试sql hikari不配置testSql,会直接使用Connection.isValid()检活
                    if (!hikariConfig.getDriverClassName().contains("mysql")) {
                        hikariConfig.setConnectionTestQuery(hikariCpConfig.getTestSql());
                    }
                    // 最小空闲连接数
                    hikariConfig.setMinimumIdle(minConns);
                    // 最大连接数
                    hikariConfig.setMaximumPoolSize(maxConns);
                    // 空闲超时(秒钟)
                    hikariConfig.setIdleTimeout(connIdleTimeout);
                    // 连接超时(秒钟)
                    hikariConfig.setConnectionTimeout(connBusyTimeout);
                    // 连接寿命(秒钟)
                    hikariConfig.setMaxLifetime(connMaxAge);
                    // 数据库方言
                    DataSource testDataSource = new HikariDataSource(hikariConfig);
                    dynamicDataSource.myMap.put(key, testDataSource);//指定key为的数据源
                }
                dynamicDataSource.setTargetDataSources(dynamicDataSource.myMap);
                dynamicDataSource.afterPropertiesSet();//一定要执行这个方法 具体含义可以看父类代码
            }
        }
    }
}
